package mulitithread;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

import static java.lang.Thread.sleep;



//控制顺序的办法
public class Interprint{
    CountDownLatch cd = new CountDownLatch(1);

    synchronized public void printNum() throws InterruptedException {
        for(int i = 1; i <= 26; i++){
            System.out.println(i);
            cd.countDown();
            this.notify();
            this.wait();
        }
        //使线程可以结束
        this.notify();
    }
    synchronized public void printChar() throws InterruptedException {
        cd.await();
        for(char i = 'A'; i < 'A' + 26; i++){
            System.out.println(i);
            this.notify();
            this.wait();
        }
        this.notify();
    }

    public static void main(String[] args) throws InterruptedException {
        Interprint ip = new Interprint();
        new Thread(() -> {
            try {
                ip.printNum();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        sleep(100); //为了先打印数字

        new Thread(() -> {
            try {
                ip.printChar();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}




//自选
// 使用volatile
//也可以使用ＡｏｍｉｃＩｎｔｅｇｅｒ

class Interprint2{
    AtomicBoolean ab = new AtomicBoolean(true);
    volatile static boolean numNow = true;

     public void printNum(){
        for(int i = 1; i <= 26; i++){
            while(!numNow){}
                System.out.println(i);
                numNow = false;
            }
     }

     public void printChar(){
        for(char i = 'A'; i < 'A' + 26; i++){
            //ab.get()
            while(numNow){}
                System.out.println(i);
                numNow = true;
            }
    }

    public static void main(String[] args) {
        Interprint2 ip = new Interprint2();
        new Thread(() -> ip.printNum()
        ).start();

        new Thread(() -> ip.printChar()
        ).start();
    }
}





 class Interprint3{
    static Thread t1 = null;
     static Thread t2 = null;
    public static void main(String[] args) throws InterruptedException {
        t1 = new Thread(() -> {
            for(int i = 1; i <= 26; i++){
                System.out.println(i);
                LockSupport.unpark(t2);
                LockSupport.park();
            }
        },"t1");


        sleep(100); //为了先打印数字
        t2 = new Thread(() -> {
            for(char i = 'A'; i < 'A' + 26; i++){
                LockSupport.park();
                System.out.println(i);
                LockSupport.unpark(t1);
            }
        },"t2");
        t1.start();
        t2.start();
    }
}

class Interprint4{
    static BlockingQueue<String> q1 = new ArrayBlockingQueue<>(1);
    static BlockingQueue<String> q2 = new ArrayBlockingQueue<>(1);

    public void printNum() throws InterruptedException {
        for(int i = 1; i <= 26; i++){
            System.out.println(i);
            q1.put("ok");//相当于上锁1
            //在这阻塞着
            q2.take();//解锁2

        }
    }
    public void printChar() throws InterruptedException {
        for(char i = 'A'; i < 'A' + 26; i++){
            q1.take();//解锁1
            System.out.println(i);
            q2.put("ok");//上锁2
            //在这阻塞着

        }
    }
    public static void main(String[] args) throws InterruptedException {
        Interprint4 ip = new Interprint4();
        new Thread(() -> {
            try {
                ip.printNum();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t1").start();

        sleep(100); //为了先打印数字

        new Thread(() -> {
            try {
                ip.printChar();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t2").start();
    }
}




class Interprint5{
    Lock lock = new ReentrantLock();
    Condition cd = lock.newCondition();


    public void printNum() throws InterruptedException {
        lock.lock();
        try {
            for(int i = 1; i <= 26; i++){
                System.out.println(i);
                cd.signalAll();
                cd.await();

            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void printChar() throws InterruptedException {
        lock.lock();
        try {
            for(char i = 'A'; i < 'A' + 26; i++){
                System.out.println(i);
                cd.signalAll();
                cd.await();
            }
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Interprint5 ip = new Interprint5();
        new Thread(()->{
            try {
                ip.printNum();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }}).start();


        sleep(100); //为了先打印数字

        new Thread(() -> {
            try {
                ip.printChar();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}


//使用两个锁的condition 略 
class Interprint6{
    Lock lock = new ReentrantLock();
    Condition cd = lock.newCondition();


    public void printNum() throws InterruptedException {
        lock.lock();
        try {
            for(int i = 1; i <= 26; i++){
                System.out.println(i);
                cd.signalAll();
                cd.await();

            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void printChar() throws InterruptedException {
        lock.lock();
        try {
            for(char i = 'A'; i < 'A' + 26; i++){
                System.out.println(i);
                cd.signalAll();
                cd.await();
            }
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Interprint5 ip = new Interprint5();
        new Thread(()->{
            try {
                ip.printNum();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }}).start();


        sleep(100); //为了先打印数字

        new Thread(() -> {
            try {
                ip.printChar();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}
